var slider = function(container, cfg,callback){
    this.container = container;
    this.cfg = $.extend(true, {scales:[0,100],showInput:false,errorColor:'#EAADAD',tipWidth:44,autoPrecision:false,cross:true,precision:2,showTip:true,minScale:null,showScale:true,dragBarCount:2,scaleCount:2,width:200,tipMoveable:false}, cfg);
    this.callback = $.extend(true, {
        onDrag:null,
        onDragEnd:null
    },callback);
    this.el = null;
    this.barEl = null;
    this.dragEls = [];
    this.dragObj = [];
    this.scaleEl = null;
    this.dragBarLength=5;
	this.timeOut_input=null;
    this.digitUnit=["","K","M","B","T","MB","BB"];
    this.unit=0;
    this.allLength=0;
    this._init();
};
slider.prototype = {
    _init: function(){
        this._setprecision();//calculate the precision and the unit
        this._setScalesNum();
        for (var i = 0; i < this.cfg.scales.length; i++) {
            var temp=parseFloat(this.cfg.scales[i]);
            this.cfg.scales[i]=this._setFitPrecision(temp);
        }
        this.scaleMax = this.cfg.scales[this.cfg.scales.length-1]-this.cfg.scales[0];
        this.el = $(this._getSliderHTML()).appendTo(this.container);
        this.el.css({width:this.cfg.width});
        this._initEls();
        this.allLength=this.cfg.width;
        for(var i =0;i<this.cfg.scales.length&&this.cfg.showScale;i++){
            var tempEl = $("<div>"+this.cfg.scales[i]+this.digitUnit[this.unit]+"</div>");
            this.scaleEl.append(tempEl);
			var temp=this._getPosition(this.cfg.scales[i])+this.dragBarLength;
			tempEl.css("left",temp);
			tempEl.css("text-indent",-tempEl.width()/2);
        }
        this.dragEls.hide();
		var position=null;
        for(var i = 0;i<this.cfg.dragBarCount;i++){
			position=this._getPosition(this.cfg.scales[i]);
            this.dragEls.eq(i).show()
            this._createDragObj(i);
			this.dragEls.eq(i).css("left",position);
			this.dragTipEls.eq(i).html(this._getTipHtml(this.cfg.scales[i]));
			if (this.cfg.showInput) {
				this.dragTipEls.eq(i).css({
					width: (this.unit == 0 ? this.cfg.tipWidth+"px" : (this.cfg.tipWidth+11)+"px")
				});//set width 55 if user can input
			}
			if (this.cfg.tipMoveable) {
				this.dragTipEls.eq(i).css({
					left: position +this.dragBarLength - this.dragTipEls.eq(i).width() / 2,
					top: -20
				});
			}
			else {
				this.dragTipEls.eq(i).css({
                    left: position+this.dragBarLength-this.dragTipEls.eq(i).width()*i,   
                    top: -20
                });
			}
        }
		this._bindInputEvent();
    },
	_getTipHtml:function(value){
		var returnValue="";
		if(!this.cfg.showInput){
			returnValue='<span>'+value+this.digitUnit[this.unit]+'</span>';
		}else{
			returnValue='<input class="qs-ui-ipt qs-ui-slider-input" value="'+value+'"></input><span>'+this.digitUnit[this.unit]+'</span>';
		}
		return returnValue;
	},
	_bindInputEvent:function(){
		if (this.cfg.showInput) {
			var self=this;
			this.dragTipEls.bind("keyup", function(e){
					e.stopPropagation();
					var origin=$(this).find("input");
					var i=parseFloat($(this).attr("index"));
					var target=origin.val();
					if(isNaN(target)){
						origin.css("background-color",self.cfg.errorColor);
						return;
					}
					var target=parseFloat(target),currentValue=self._convertPrecisionToValue(target);
					if((i==0&&target >= self.cfg.scales[0] && currentValue <= self._getDragValue(1).value)||(i==1&&target <= self.cfg.scales[1] && currentValue >= self._getDragValue(0).value)) {
						self.dragEls.eq(i).css("left", self._getPosition(target));
						if (typeof self.callback.onDragEnd == 'function') {
							clearTimeout(self.timeOut_input);
							self.timeOut_input=setTimeout(function(){
								self.callback.onDragEnd(self._getDragRealValue(0), self._getDragRealValue(1));
							},1000);
						}
						origin.css("background-color", "transparent");
						return true;
					}else{
						origin.css("background-color",self.cfg.errorColor);
						return ;
					}
			});
		}
	},
	_setScalesNum:function(){
		if(this.cfg.scales.length==this.cfg.scaleCount) return;
		var temp =[];
		var num = (this.cfg.scales[1]-this.cfg.scales[0])/this.cfg.scaleCount;
		for(var i =0;i<this.cfg.scaleCount;i++){
		  temp.push(this.cfg.scales[0]+num);
		}
		this.cfg.scales = temp;
		
	},
    _setDigitPrecision:function(data){
        var strData=String(Math.abs(data));
        var position=strData.indexOf(".");
        if(position==-1) position=strData.length;
        var temp=Math.floor(position/3)-(position>0?(position%3>0?0:1):0);
        this.unit=Math.max(temp,this.unit);
    },
    _setprecision:function(){
        for (var i = 0; i < this.cfg.scales.length; i++) {
            var data=this.cfg.scales[i];
            if (isNaN(data)) 
                return;
            data=parseFloat(data)
            if (this.cfg.autoPrecision) {
                var str = String(data);
                for (var l = str.length, i = l - 1; i >= 1; i--) {
                    var temp = str[i];
                    if (temp == '.') {
                        this.cfg.precision = Math.max(l - 1 - i, this.cfg.precision);
                        break;
                    }
                }
            }
            this._setDigitPrecision(data);
        }
    },
    _setFitPrecision:function(data){
        if(isNaN(data)) return;
        var tag=data<0?true:false;
		var cancelwrong=Math.pow(10, -this.cfg.precision);
        if(this.unit>0){
            data=data*Math.pow(10, -this.unit*3);
			if(data<cancelwrong&&data>0){
				data=0;
			}
        }
        var temp=parseFloat(data.toFixed(this.cfg.precision));
        if(temp==data) return data;
        var isMore=temp>data?true:false;
        var returnValue=temp;
        if((tag&&isMore)||(!tag&&!isMore)){
            if(tag){
                returnValue =temp-cancelwrong;
            }else{
                returnValue =temp+cancelwrong;
            }
            returnValue=parseFloat(returnValue.toFixed(this.cfg.precision));
        }
        return returnValue;
    },
	_convertPrecisionToValue:function(data){
		var temp=parseFloat(data.toFixed(this.cfg.precision));
		return this.unit>0?temp*Math.pow(10, this.unit*3):temp;
	},
    _createDragObj:function(v){
        var self =this;
        this.dragObj[v] = new Util.Dragable(this.dragEls[v], {
            onDragStart: function(e, proxy){
                self._setMoveScope(v);
                //self.dragObj[v].setContainment(0, 0, this.allLength , 0);
            },
            onDrag: function(e, proxy){
                self._onSliderBarDrag(v,proxy)
            },
            onDragEnd: function(e, proxy){
                proxy.show();
                self._onSliderBarDragEnd(v,proxy);
            }
        }, {
            autoProxy: false,
            proxy: this.dragEls.eq(v),
            delay: 10,
            direction: 'x'
        });
		//this.dragEls.eq(i).css("left", this._getPosition(this.cfg.scales[i]));
    },
    _setMoveScope:function(v){
        if (!this.cfg.cross) {
            this.dragObj[v].setContainment(0, 0, this.allLength, 0);
        }else if (v == 0) {
            this.dragObj[v].setContainment(0, 0, this.dragEls.eq(1).position().left, 0);
        }else {
            this.dragObj[v].setContainment(this.dragEls.eq(0).position().left, 0, this.allLength, 0);
        }
    },
    _onSliderBarDrag:function(v,proxy){
        var self = this;
        var tempPos = proxy.position().left / self.allLength * self.scaleMax+this.cfg.scales[0];
        if(self.cfg.showTip){
            self.dragTipEls.eq(v).html(tempPos.toFixed(self.cfg.precision)+self.digitUnit[self.unit]);
        }
//        self.callback.onDrag(v, {
//            percent: proxy.position().left / self.allLength,
//            value: tempPos
//        });
        if (self.callback.onDrag != null) {
            self.callback.onDrag(this._getDragValue(0),this._getDragValue(1));
        }
        this._changeTipPosition(v);
    },
    _getDragValue:function(v){
        var  proxy = this.dragEls.eq(v);
		var  precent= proxy.position().left/this.allLength ;
        return {percent:precent,value:this._convertPrecisionToValue(precent * this.scaleMax+this.cfg.scales[0])};
    },
	_getDragRealValue:function(v){
		var value=parseFloat(this.dragTipEls.eq(v).find("input").val());
		var precent=value!=0?value/this.cfg.scales[this.cfg.scales.length-1]:0;
		return {percent:precent,value:this._convertPrecisionToValue(value)};
	},
	_divideData:function(divided,divider,precision){
		var pre=precision||5;
		return parseFloat((divided*Math.pow(10,pre)/divider)*Math.pow(10,-pre)).toFixed(pre);
	},
    getDragValue:function(){
        return [this._getDragValue(0),this._getDragValue(1)];
    },
    _changeTipPosition:function(v){
        var self =this;
        if(this.cfg.tipMoveable){
            self.dragTipEls.eq(v).css({
                left: self.dragEls.eq(v).position().left - self.dragTipEls.eq(v).width() / 2 + self.dragBarLength,
                top: -20
            });
        }
        var tempPos = self.dragEls.eq(v).position().left / self.allLength * self.scaleMax+this.cfg.scales[0];
        //tempPos.toFixed(self.cfg.precision)
		if(self.cfg.showTip){
            self.dragTipEls.eq(v).html(this._getTipHtml(parseFloat(tempPos.toFixed(self.cfg.precision))));
        }
    },
    _onSliderBarDragEnd:function(v,proxy){
        var self = this;
        var tempPos = proxy.position().left / self.allLength * self.scaleMax+this.cfg.scales[0];
//        self.callback.onDragEnd(v, {
//            percent: proxy.position().left / self.allLength,
//            value: tempPos
//        });

        if (self.callback.onDragEnd != null) {
            self.callback.onDragEnd(this._getDragValue(0), this._getDragValue(1));
        }
        if(self.cfg.minScale==null){
            return;
        }
        var tempPos = proxy.position().left / self.allLength * self.scaleMax;
        var tempScale = tempPos / self.cfg.minScale, s = Math.round(tempPos / self.cfg.minScale);
        proxy.css({
            left: s * self.allLength * self.cfg.minScale / self.scaleMax
        })
        self._onSliderBarDrag(v, proxy)
    },
    setSliderBarValue: function(v,outside){
        if (!v || v.length == 0) {
            return;
        }
        for (var i = 0; i < v.length; i++) {
			var temp=v[i];
			if (outside) {
				temp=this._setFitPrecision(temp);
				if(i==0&&!isNaN(temp)){
					temp=Math.max(temp,this.cfg.scales[0])
				}else if(!isNaN(temp)){
					temp=Math.min(temp,this.cfg.scales[i])
				}
			}
            this.dragEls.eq(i).css("left", this._getPosition(temp));
            this._changeTipPosition(i);
        }
    },
	reset:function(){
        this.setSliderBarValue(this.cfg.scales);
	},
    _getPosition:function(v){
		var left=(v-this.cfg.scales[0])/(this.cfg.scales[this.cfg.scales.length-1]-this.cfg.scales[0])*this.allLength;
        return left;
    },
    _getSliderHTML: function(){
        return "<div class='qs-ui-slider'><div class='qs-ui-slider-bar'></div><div class='qs-ui-slider-drag-wrap'><div class='qs-ui-slider-drag-tip' index='0'></div><div class='qs-ui-slider-drag-tip' index='1'></div><a class='drag-trigger'>&nbsp;</a><a class='drag-trigger' style=''>&nbsp;</a></div><div class='qs-ui-slider-scales-wrap'></div></div>";
    },
    _initEls: function(){
        this.barEl = this.el.find(".qs-ui-slider-bar");
        this.dragEls = this.el.find(".drag-trigger");
        this.dragTipEls = this.el.find(".qs-ui-slider-drag-tip");
		if(this.cfg.showInput){
			this.dragTipEls.addClass("qs-ui-slider-ipt");
		}
        this.scaleEl = this.el.find(".qs-ui-slider-scales-wrap");
		this.barEl.css("left", this.dragBarLength);
        var self = this;
        this.barEl.bind("click.slider",function(e){
            var o = $(e);
            var x = o[0].pageX-self.el.offset().left-self.dragBarLength;
            var flag = Math.abs(x-self.dragEls.eq(0).position().left)<Math.abs(x-self.dragEls.eq(1).position().left)?0:1;
            self.dragEls.eq(flag).css({left:x})
            self._onSliderBarDrag(flag,self.dragEls.eq(flag));
            self._onSliderBarDragEnd(flag,self.dragEls.eq(flag));
            
        })
    }
}

